Nokogiri 鋸 教程翻译 :在XML/HTML文档中搜索,Searching a XML/HTML Document
假设,妳已有以下这个文档:
[shows.xml] <root> <sitcoms> <sitcom> <name>Married with Children</name> <characters> <character>Al Bundy</character> <character>Bud Bundy</character> <character>Marcy Darcy</character> </characters> </sitcom> <sitcom> <name>Perfect Strangers</name> <characters> <character>Larry Appleton</character> <character>Balki Bartokomous</character> </characters> </sitcom> </sitcoms> <dramas> <drama> <name>The A-Team</name> <characters> <character>John "Hannibal" Smith</character> <character>Templeton "Face" Peck</character> <character>"B.A." Baracus</character> <character>"Howling Mad" Murdock</character> </characters> </drama> </dramas> </root>
|
进一步假设,妳想要搜索到这个文档中所有的演出(shows)里所有的角色(characters)的列表。
@doc = Nokogiri :: XML ( File .open ( "shows.xml" )) @doc .xpath("//character") # => ["<character>Al Bundy</character>", # "<character>Bud Bundy</character>", # "<character>Marcy Darcy</character>", # "<character>Larry Appleton</character>", # "<character>Balki Bartokomous</character>", # "<character>John \"Hannibal\" Smith</character>", # "<character>Templeton \"Face\" Peck</character>", # "<character>\"B.A.\" Baracus</character>", # "<character>\"Howling Mad\" Murdock</character>"]
|
与 Node 相关 的方法( xpath 和 css )实际返回的是一个 NodeSet ,它类似于一个数组,包含着文档中相匹配的那些节点。
characters [ 0 ] .to_s # => "<character>Al Bundy</character>"
|
妳可以使用自己喜欢的任何XPath或CSS查询语句(参考XPath和CSS语法一节,以了解更多信息)。
@doc .xpath ( "//dramas//character" ) # => ["<character>John \"Hannibal\" Smith</character>", # "<character>Templeton \"Face\" Peck</character>", # "<character>\"B.A.\" Baracus</character>", # "<character>\"Howling Mad\" Murdock</character>"]
|
注意,妳甚至可以在XML 文档中使用CSS 查询!
characters = @doc .css("sitcoms name") # => ["<name>Married with Children</name>", "<name>Perfect Strangers</name>"] # !> assigned but unused variable - characters
一般来说,CSS查询是最简单、最简洁地表达妳要寻找的内容的方式,所以,勇敢地使用它们吧!
如果妳知道妳 只 会获取 到单条结果的话,那么,妳可以使用快捷的 at_css 和 at_xpath ,而无需再去访问NodeSet 中的第一个元素。
@doc .css ( "dramas name" ) .first # => "<name>The A-Team</name>" @doc .at_css("dramas name") # => "<name>The A-Team</name>"
|
就像 Ruby代码 一样, XML 也会发生名字冲突。例如,汽车零件店会卖轮胎,而自行车店也会卖轮胎。 它们可能都会使用 “tire”标记 来描述它们所卖的轮胎。然而 ,我们需要区分出汽车轮胎和自行车轮胎。 这个时候,命名空间就能派上用场了。
命名空间,将一个唯一的URL 与标记关联起来。让我们看一看汽车零件店的XML,以及自行车店的:
[parts.xml] <parts> <!-- Alice的汽车零件店 --> <inventory xmlns= "http://alicesautoparts.com/" > <tire>all weather</tire> <tire>studded</tire> <tire>extra wide</tire> </inventory> <!-- Bob的自行车店 --> <inventory xmlns= "http://bobsbikes.com/" > <tire>street</tire> <tire>mountain</tire> </inventory> </parts>
|
由于 这些 URL 是唯一的,所以,我们可以将我们的查询关联到某个 URL 上,这样,就获取到只属于 那个 url的轮胎:
@doc = Nokogiri :: XML ( File .read ( "parts.xml" ))
car_tires = @doc .xpath('//car:tire', 'car' => 'http://alicesautoparts.com/') # !> assigned but unused variable - car_tires
# => ["<tire>all weather</tire>", # !> assigned but unused variable - bike_tires
# "<tire>studded</tire>",
# "<tire>extra wide</tire>"]
bike_tires = @doc .xpath('//bike:tire', 'bike' => 'http://bobsbikes.com/')
# => ["<tire>street</tire>", "<tire>mountain</tire>"]
为了简化命名空间的注册动作, nokogiri 会自动为妳将它在根节点上找到的命名空间注册上。 Nokogiri 会将声明中的名字与所提供的URL 关联起来。如果我们遵循这个命名惯例,那么,我们就可以缩短代码。
例如,下面这个原子文章列表:
[atom.xml] <?xml version="1.0" encoding="utf-8"?> <feed xmlns= "http://www.w3.org/2005/Atom" > <title>Example Feed</title> <link href= "http://example.org/" /> <updated>2003-12-13T18:30:02Z</updated> <author> <name>John Doe</name> </author> <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id> <entry> <title>Atom-Powered Robots Run Amok</title> <link href= "http://example.org/2003/12/13/atom03" /> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2003-12-13T18:30:02Z</updated> <summary>Some text.</summary> </entry> </feed>
|
如果我们遵循这个惯例,那么,我们可以使用以下代码来获取到所有的title 标记
@doc .xpath('//xmlns:title') # => ["<title>Example Feed</title>", "<title>Atom-Powered Robots Run Amok</title>"]
不过,别以为事情就是这么简单。妳并非一定要用 XPath才能利用命名空间 。也可以使用 CSS选择 器。 在 CSS 中,使用管道符号来表示命名空间搜索。
让我们将上一个搜索用CSS重写:
@doc .css('xmlns|title') # => ["<title>Example Feed</title>", "<title>Atom-Powered Robots Run Amok</title>"]
在使用CSS的时候,如果命名空间被称作“xmlns”,那么,妳甚至可以省略命名空间名字。也就是说,使用CSS的话,可以这样写:
@doc .css ( 'title' ) # => ["<title>Example Feed</title>", "<title>Atom-Powered Robots Run Amok</title>"]
|
命名空间本身 是一个广泛的话题。如果妳想了解更多示例,那么,请阅读 这篇文章 或者 向 邮件列表 发送一封邮件,我们会尽力相助。
懒 == 高效,所以,我并不会批评妳懒。 :)
如果 妳遇到一个带有命名空间的 XML文档,但是 却想要完全无视它们,那么,妳可以调用XML::Document 的 remove_namespaces 方法,来去掉所有的命名空间。当然,如果该文档中包含了名字相同而命名空间不同的节点的话,则,如今它们就会产生歧义了。但是,妳懒!妳不在意这个!
Scarlett Johansson
debian
Your opinionsHxLauncher: Launch Android applications by voice commands